package com.starrocks.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 数据类型转换器
 * 处理StarRocks和TiDB之间的数据类型差异
 */
@Slf4j
@Service
public class DataTypeConverter {

    /**
     * 转换单个值
     * 
     * @param value 原始值
     * @param columnName 列名（用于日志）
     * @return 转换后的值
     */
    public Object convertValue(Object value, String columnName) {
        if (value == null) {
            return null;
        }

        try {
            // 1. 处理字节数组（可能是BITMAP、HLL等特殊类型）
            if (value instanceof byte[]) {
                return convertBinaryType((byte[]) value, columnName);
            }

            // 2. 处理时间类型
            if (value instanceof java.sql.Date) {
                return convertDate((java.sql.Date) value);
            }

            if (value instanceof java.sql.Time) {
                return convertTime((java.sql.Time) value);
            }

            if (value instanceof Timestamp) {
                return convertTimestamp((Timestamp) value);
            }

            if (value instanceof LocalDateTime) {
                return Timestamp.valueOf((LocalDateTime) value);
            }

            if (value instanceof LocalDate) {
                return java.sql.Date.valueOf((LocalDate) value);
            }

            // 3. 处理数值类型
            if (value instanceof BigDecimal) {
                return convertDecimal((BigDecimal) value);
            }

            // 4. 处理布尔类型（StarRocks可能用TINYINT(1)）
            if (value instanceof Boolean) {
                return ((Boolean) value) ? 1 : 0;
            }

            // 5. 处理字符串类型（处理特殊字符）
            if (value instanceof String) {
                return convertString((String) value);
            }

            // 6. 处理数组类型（StarRocks的ARRAY）
            if (value.getClass().isArray()) {
                return convertArray(value, columnName);
            }

            // 7. 其他类型直接返回
            return value;

        } catch (Exception e) {
            log.warn("类型转换失败 - 列: {}, 值: {}, 类型: {}, 错误: {}", 
                columnName, value, value.getClass().getName(), e.getMessage());
            return value; // 转换失败时返回原值
        }
    }

    /**
     * 转换整个数据行
     * 
     * @param data 原始数据
     * @param tableName 表名（用于日志）
     * @return 转换后的数据
     */
    public Map<String, Object> convertRowData(Map<String, Object> data, String tableName) {
        Map<String, Object> converted = new HashMap<>();
        
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            String columnName = entry.getKey();
            Object value = entry.getValue();
            Object convertedValue = convertValue(value, columnName);
            converted.put(columnName, convertedValue);
        }
        
        return converted;
    }

    /**
     * 转换二进制类型
     * StarRocks的BITMAP、HLL等类型在TiDB中可能需要转换为字符串或JSON
     */
    private Object convertBinaryType(byte[] bytes, String columnName) {
        // 如果是小的字节数组，可能是普通的BINARY/VARBINARY
        if (bytes.length < 1024) {
            return bytes;
        }
        
        // 大的字节数组可能是BITMAP或HLL，转换为Base64字符串
        log.debug("将二进制数据转换为Base64字符串 - 列: {}, 大小: {} bytes", columnName, bytes.length);
        return java.util.Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * 转换日期类型
     */
    private Object convertDate(java.sql.Date date) {
        // TiDB支持DATE类型，直接返回
        return date;
    }

    /**
     * 转换时间类型
     */
    private Object convertTime(java.sql.Time time) {
        // TiDB支持TIME类型，直接返回
        return time;
    }

    /**
     * 转换时间戳类型
     * 处理精度问题
     */
    private Object convertTimestamp(Timestamp timestamp) {
        // StarRocks的DATETIME精度可能与TiDB不同
        // TiDB默认支持微秒精度(6位)
        return timestamp;
    }

    /**
     * 转换DECIMAL类型
     * 处理精度和范围问题
     */
    private Object convertDecimal(BigDecimal decimal) {
        // 检查精度是否超出TiDB限制
        // TiDB DECIMAL最大精度为65位，标度最大30位
        int precision = decimal.precision();
        int scale = decimal.scale();
        
        if (precision > 65) {
            log.warn("DECIMAL精度超出TiDB限制 - 精度: {}, 将进行截断", precision);
            // 可以选择截断或抛出异常
            return decimal.setScale(Math.min(scale, 30), BigDecimal.ROUND_HALF_UP);
        }
        
        return decimal;
    }

    /**
     * 转换字符串类型
     * 处理特殊字符和编码问题
     */
    private Object convertString(String str) {
        // 处理特殊字符
        if (str.isEmpty()) {
            return str;
        }
        
        // 检查是否包含NULL字符（MySQL/TiDB不支持）
        if (str.contains("\u0000")) {
            log.debug("字符串包含NULL字符，将被移除");
            return str.replace("\u0000", "");
        }
        
        // 检查长度（根据字段类型可能需要截断）
        // 这里只是示例，实际应该根据表结构来判断
        return str;
    }

    /**
     * 转换数组类型
     * StarRocks的ARRAY类型在TiDB中可能需要转换为JSON
     */
    private Object convertArray(Object array, String columnName) {
        log.debug("检测到数组类型 - 列: {}, 将转换为JSON字符串", columnName);
        
        try {
            // 将数组转换为JSON字符串
            StringBuilder json = new StringBuilder("[");
            int length = java.lang.reflect.Array.getLength(array);
            
            for (int i = 0; i < length; i++) {
                if (i > 0) {
                    json.append(",");
                }
                Object element = java.lang.reflect.Array.get(array, i);
                if (element instanceof String) {
                    json.append("\"").append(element).append("\"");
                } else {
                    json.append(element);
                }
            }
            
            json.append("]");
            return json.toString();
            
        } catch (Exception e) {
            log.warn("数组转换失败 - 列: {}, 返回空数组", columnName);
            return "[]";
        }
    }

    /**
     * 检查值是否需要转换
     */
    public boolean needsConversion(Object value) {
        if (value == null) {
            return false;
        }
        
        // 这些类型可能需要特殊处理
        return value instanceof byte[] 
            || value instanceof BigDecimal
            || value.getClass().isArray()
            || (value instanceof String && ((String) value).contains("\u0000"));
    }

    /**
     * 获取值的类型信息（用于调试）
     */
    public String getTypeInfo(Object value) {
        if (value == null) {
            return "NULL";
        }
        
        String className = value.getClass().getSimpleName();
        
        if (value instanceof byte[]) {
            return className + "[" + ((byte[]) value).length + "]";
        }
        
        if (value instanceof String) {
            return className + "[" + ((String) value).length() + "]";
        }
        
        if (value.getClass().isArray()) {
            return className + "[" + java.lang.reflect.Array.getLength(value) + "]";
        }
        
        return className;
    }
}

